package com.topnav.mc.uitls.gps;

import java.util.List;

/**
 * @Author: kenny
 * @Date: 2023/11/13 15:44
 */
public class GpsUtils {
    static double PI=3.14159265358979324;
    static double ee = 0.00669342162296594323; //  ee: 椭球的偏心率。
    static double a = 6378245.0; //  a: 卫星椭球坐标投影到平面地图坐标系的投影因子。

    /**
     * 判断某个是点是否在围栏里
     * @param pt
     * @param polygon
     * @return
     */
    public static boolean PointInPolygon(Gps pt, List<Gps> polygon){
        if (polygon.size() < 3){
            return false;
        }

        Gps gps1=new Gps();
        Gps gps2=new Gps();
        Gps gps=null;
        int sum=0;
        double longitude=0;
        for (int i = 0; i < polygon.size(); i++) {
            gps = polygon.get(i);
            if (i == polygon.size() - 1) {
                //最后一条
                gps1.setLongitude(polygon.get(i).getLongitude()).setLatitude(polygon.get(i).getLatitude());
                gps2.setLongitude(polygon.get(0).getLongitude()).setLatitude(polygon.get(0).getLatitude());
            } else {
                gps1.setLongitude(polygon.get(i).getLongitude()).setLatitude(polygon.get(i).getLatitude());
                gps2.setLongitude(polygon.get(i+1).getLongitude()).setLatitude(polygon.get(i+1).getLatitude());
            }

            if (((pt.getLatitude() >= gps1.getLatitude()) && (pt.getLatitude() < gps2.getLatitude())) ||
                    ((pt.getLatitude() >= gps2.getLatitude()) && (pt.getLatitude() < gps1.getLatitude()))) {
                if (Math.abs(gps1.getLatitude() - gps2.getLatitude()) > 0) {
                    //The x-coordinate at point A where the ray intersects the edge to the left

                    longitude = gps1.getLongitude() - (
                            (gps1.getLongitude() - gps2.getLongitude()) * (gps1.getLatitude() - pt.getLatitude())
                    ) / (
                            gps1.getLatitude() - gps2.getLatitude()
                    );

                    if (longitude < pt.getLongitude())
                        sum++;
                }
            }
        }
        if (sum % 2 != 0)
            return true;
        return false;
    };


    /**
     * WG-S84 转为 GCJ-02
     * @param wgsLat
     * @param wgsLon
     * @returns {{lon: *, lat: *}|{lon, lat}}
     * @constructor
     */
    public static Gps gps84ToGcj02(double wgsLat ,double wgsLon ){
        if (outOfChina(wgsLat, wgsLon)) {
            return  new Gps(wgsLon,wgsLat);
        }
        //return new Gps(wgsLon,wgsLat);
        Gps d = delta(wgsLat, wgsLon);
        return new Gps(wgsLon + d.getLongitude(),wgsLat + d.getLatitude());
    }

    /**
     * 84 to 火星坐标系 (GCJ-02)
     * @param lat
     * @param lng
     * @returns {[number, number]}
     * @constructor
     */
    public static Gps gcj02ToGps84(double lat, double lng){
        //var lat = +lat;
        //var lng = +lng;

        if (outOfChina(lat, lng)) {
            return new Gps(lng,lat);
        } else {
            double dlat = transformLat(lng - 105.0, lat - 35.0);
            double dlng = transformLon(lng - 105.0, lat - 35.0);
            double radlat = lat / 180.0 * PI;
            double magic = Math.sin(radlat);
            magic = 1 - ee * magic * magic;
            double sqrtmagic = Math.sqrt(magic);
            dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
            dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
            double mglat = lat + dlat;
            double mglng = lng + dlng;
            return new Gps(lng * 2 - mglng, lat * 2 - mglat);
        }
    }


    /**
     * 是否在中国境内
     * @param lat
     * @param lon
     * @returns {boolean}
     */
    private static boolean outOfChina(double lat, double lon){
/*        if (lon < 72.004 || lon > 137.8347)
            return true;
        if (lat < 0.8293 || lat > 55.8271)
            return true;*/
        return false;
    }

    /** 的转换--提供javascript版本转换代码
     * WG-S84: GPS仪器记录的经纬度信息，Google Earth采用，Google Map中国范围外使用，高德地图中国范围外使用。
     GCJ-02: 火星坐标系，中国国家测绘局制定的坐标系统，由WGS-84加密后的坐标。Google中国和搜搜地图，arcgis地图，高德地图
     （在国内是不允许直接用WGS84坐标系标注的，必须经过加密后才能用。必须至少使用GCJ－02坐标系，或者使用在GCJ－02加密后再进行加密的坐标系，如百度坐标系）
     BD-09:百度坐标，GCJ-02加密后的坐标系，只适用于百度地图
     */
    private static Gps delta(double lat, double lon){
        //ee = 0.00669342162296594323;
        double dLat = transformLat(lon - 105.0, lat - 35.0);
        double dLon = transformLon(lon - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * PI;
        double magic = Math.sin(radLat);


        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
        return new Gps(dLon,dLat);
    }

    private static double transformLat(double x,double y){
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    private static double transformLon(double x,double y){
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
        return ret;
    }
}
